Crate pasetors

source ·
Expand description

Getting started

This library has two ways of working with tokens. The first is the local and public module, which the below examples make use of. These use the latest version of PASETO for tokens, along with claims::Claims, to enable a straightforward way of defining common claims. claims::ClaimsValidationRules lets you define validation rules, that are covered when using the local and public module. Using these modules means that validation of registered claims is handled automatically.

If more control over the input is needed, and validation is handled manually, the version4/version2 module provide a lower-level interface, where payloads are be provided as byte-slices.

NOTE: claims, local and public modules are only available with default-features enabled.

Creating and verifying public tokens

use pasetors::claims::{Claims, ClaimsValidationRules};
use pasetors::keys::{Generate, AsymmetricKeyPair, AsymmetricSecretKey, AsymmetricPublicKey};
use pasetors::{public, Public, version4::V4};
use pasetors::token::{UntrustedToken, TrustedToken};
use core::convert::TryFrom;

// Setup the default claims, which include `iat` and `nbf` as the current time and `exp` of one hour.
// Add a custom `data` claim as well.
let mut claims = Claims::new()?;
claims.add_additional("data", "A public, signed message")?;

// Generate the keys and sign the claims.
let kp = AsymmetricKeyPair::<V4>::generate()?;
let pub_token = public::sign(&kp.secret, &claims, None, Some(b"implicit assertion"))?;

// Decide how we want to validate the claims after verifying the token itself.
// The default verifies the `nbf`, `iat` and `exp` claims. `nbf` and `iat` are always
// expected to be present.
// NOTE: Custom claims, defined through `add_additional()`, are not validated. This must be done
// manually.
let validation_rules = ClaimsValidationRules::new();
let untrusted_token = UntrustedToken::<Public, V4>::try_from(&pub_token)?;
let trusted_token = public::verify(&kp.public, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?;
assert_eq!(&claims, trusted_token.payload_claims().unwrap());

let claims = trusted_token.payload_claims().unwrap();

println!("{:?}", claims.get_claim("data"));
println!("{:?}", claims.get_claim("iat"));

Creating and verifying local tokens

use pasetors::claims::{Claims, ClaimsValidationRules};
use pasetors::keys::{Generate, SymmetricKey};
use pasetors::{local, Local, version4::V4};
use pasetors::token::UntrustedToken;
use core::convert::TryFrom;

// Setup the default claims, which include `iat` and `nbf` as the current time and `exp` of one hour.
// Add a custom `data` claim as well.
let mut claims = Claims::new()?;
claims.add_additional("data", "A secret, encrypted message")?;

// Generate the key and encrypt the claims.
let sk = SymmetricKey::<V4>::generate()?;
let token = local::encrypt(&sk, &claims, None, Some(b"implicit assertion"))?;

// Decide how we want to validate the claims after verifying the token itself.
// The default verifies the `nbf`, `iat` and `exp` claims. `nbf` and `iat` are always
// expected to be present.
// NOTE: Custom claims, defined through `add_additional()`, are not validated. This must be done
// manually.
let validation_rules = ClaimsValidationRules::new();
let untrusted_token = UntrustedToken::<Local, V4>::try_from(&token)?;
let trusted_token = local::decrypt(&sk, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?;
assert_eq!(&claims, trusted_token.payload_claims().unwrap());

let claims = trusted_token.payload_claims().unwrap();

println!("{:?}", claims.get_claim("data"));
println!("{:?}", claims.get_claim("iat"));

Additional claims and their validation

Setting registered claims and how to validate them

use pasetors::claims::{Claims, ClaimsValidationRules};

// `iat`, `nbf` and `exp` have been set automatically, but could also be overridden.
let mut claims = Claims::new()?;
claims.issuer("paragonie.com")?;
claims.subject("test")?;
claims.audience("pie-hosted.com")?;
claims.expiration("2039-01-01T00:00:00+00:00")?;
claims.not_before("2038-04-01T00:00:00+00:00")?;
claims.issued_at("2038-03-17T00:00:00+00:00")?;
claims.token_identifier("87IFSGFgPNtQNNuw0AtuLttPYFfYwOkjhqdWcLoYQHvL")?;

let mut validation_rules = ClaimsValidationRules::new();
validation_rules.validate_issuer_with("paragonie.com");
validation_rules.validate_subject_with("test");
validation_rules.validate_audience_with("pie-hosted.com");
validation_rules.validate_token_identifier_with("87IFSGFgPNtQNNuw0AtuLttPYFfYwOkjhqdWcLoYQHvL");

// The token has been set to be issued in the future and not valid yet, so validation fails.
assert!(validation_rules.validate_claims(&claims).is_err());

Non-expiring tokens

use pasetors::claims::{Claims, ClaimsValidationRules};

// Non-expiring tokens
let mut claims = Claims::new()?;
claims.add_additional("data", "A public, signed message")?;
claims.non_expiring();
// Now claims can be validated as non-expiring when we define the validation rule as:
let mut validation_rules = ClaimsValidationRules::new();
validation_rules.allow_non_expiring();
use pasetors::paserk::{FormatAsPaserk, Id};
use pasetors::claims::{Claims, ClaimsValidationRules};
use pasetors::footer::Footer;
use pasetors::keys::{Generate, AsymmetricKeyPair};
use pasetors::{public, Public, version4::V4};
use pasetors::token::UntrustedToken;
use core::convert::TryFrom;

// Generate the key used to later sign a token.
let kp = AsymmetricKeyPair::<V4>::generate()?;
// Serialize the public key to PASERK "pid".
let mut pid = Id::from(&kp.public);
// Add the "pid" to the "kid" claim of a footer.
let mut footer = Footer::new();
footer.key_id(&pid);
footer.add_additional("custom_footer_claim", "custom_value")?;

let mut claims = Claims::new()?;
let pub_token = public::sign(&kp.secret, &claims, Some(&footer), Some(b"implicit assertion"))?;

// If we receive a token that needs to be verified, we can still try to parse a Footer from it
// as long one was used during creation, if we don't know it beforehand.
let validation_rules = ClaimsValidationRules::new();
let untrusted_token = UntrustedToken::<Public, V4>::try_from(&pub_token)?;
let trusted_token = public::verify(&kp.public, &untrusted_token, &validation_rules, None, Some(b"implicit assertion"))?;
let trusted_footer = Footer::try_from(&trusted_token)?;

let mut kid = String::new();
pid.fmt(&mut kid).unwrap();
assert_eq!(trusted_footer.get_claim("kid").unwrap().as_str().unwrap(), kid);

PASERK serialization

use pasetors::paserk::FormatAsPaserk;
use pasetors::keys::{Generate, SymmetricKey};
use pasetors::version4::V4;
use core::convert::TryFrom;

// Generate the key and serialize to and from PASERK.
let sk = SymmetricKey::<V4>::generate()?;
let mut paserk = String::new();
sk.fmt(&mut paserk).unwrap();
let sk = SymmetricKey::<V4>::try_from(paserk.as_str())?;

Re-exports

Modules